/*
**  Copyright (c) 2014 Michael Liu(michael.liu.point@gmail.com).
**
**  Project: Gateway Unified Management Platform
**  File:    common.h
**  Author:  Michael
**  Date:    03/20/2014
**
**  Purpose:
**    common defines.
*/

#ifndef __GUM_COMMON_H__
#define __GUM_COMMON_H__

#ifdef __cplusplus
extern "C" {
#endif				/* __cplusplus */

/* Include files. */

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>

#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>

#include <sys/un.h>
#include <sys/stat.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>

#include <sys/mman.h>

#include <signal.h>
#include <arpa/inet.h>

#include <time.h>

#include "log.h"

/* Macro constant definitions. */

#define POISON_POINTER_DELTA 0
#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)

#define CONFIG_MASK_NUM					(8)

#define FILE_PATH_NAME_STR_MAX			(128 + 1)

#define RC_DESCRIPTION_MAX_SIZE			(128 + 1)

#define RC_IPV4_STR_MAX_SIZE			(15 + 1)
#define RC_IPV4_STR_LEN					(4)
#define RC_MAC_STR_MAX_SIZE				(17 + 1)
#define RC_VERSION_STR_MAX				(32 + 1)
#define RC_HOSTNAME_STR_MAX_SIZE		(15 + 1)
#define RC_FILE_NAME_STR_MAX			FILE_PATH_NAME_STR_MAX

#define SYSMGR_LOG_FILE					"/var/log/sysmgr.log"
#define SYSMGR_LOG_LEVEL				eLOG_LEVEL_DEBUG

/* Type definitions. */

	typedef enum {
		eRET_MIN = 0,
		eRET_SUCCESS = eRET_MIN,
		eRET_FAILURE,
		eRET_INVALID_ARG,
		eRET_INVALID_STATE,
		eRET_NO_RESOURCE,
		eRET_ALREADY_EXIST,
		eRET_NOT_EXIST,
		eRET_NOT_SUPPORT,
		eRET_TIMEOUT,
		eRET_PENDDING,
		eRET_MAX,
		/* To use same size of unsigned int */
		eRET_PADDING = ((unsigned int)~0),
	} e_ret;

	typedef enum {
		eBOOL_MIN = 0,
		eBOOL_FALSE = eBOOL_MIN,
		eBOOL_TRUE,
		eBOOL_MAX,
		eBOOL_PADDING = ((unsigned int)~0),
	} e_bool;

	typedef pthread_mutex_t t_mutex;

	typedef struct date_time {
		unsigned char day;
		unsigned char hour;
		unsigned char minute;
		unsigned char second;
		unsigned short year;
		unsigned char month;
	} t_date_time;

	struct list_head {
		struct list_head *next, *prev;
	};

	struct hlist_head {
		struct hlist_node *first;
	};

	struct hlist_node {
		struct hlist_node *next, **pprev;
	};

	typedef struct {
		unsigned long mask[CONFIG_MASK_NUM];
	} tmask;

/* External function declarations. */

/* Macro API definitions. */

#define ASSERT(x) \
  do {                                                                        \
      if (!(x)) {                                                             \
          sysmgr_err("%s\n", # x);                                            \
          exit (-1);                                                          \
      }                                                                       \
  } while (0)

#define bit_to_mask(bit)					(1 << (bit))
#define mask_set_bit(mask, bit)				((mask) |= bit_to_mask(bit))
#define mask_clear_bit(mask, bit)			((mask) &= (~(bit_to_mask(bit))))
#define mask_test_bit(mask, bit)			(((mask) & bit_to_mask(bit)) == bit_to_mask(bit))
#define mask_test_bitmask(mask, bitmask)	(((mask) & (bitmask)) != 0)

#define static_mutex_define(mutexM) \
static t_mutex mutexM = PTHREAD_MUTEX_INITIALIZER;

#define extern_mutex_define(mutexM) \
t_mutex mutexM = PTHREAD_MUTEX_INITIALIZER;

#define extern_mutex(mutexM) \
extern t_mutex mutexM;

#define mutex_lock(mutexPM)    pthread_mutex_lock(mutexPM)
#define mutex_trylock(mutexPM) pthread_mutex_trylock(mutexPM)
#define mutex_unlock(mutexPM)  pthread_mutex_unlock(mutexPM)

#define sysmgr_db_mutex_lock() mutex_lock(&sysmgr_db_mutex)
#define sysmgr_db_mutex_unlock() mutex_unlock(&sysmgr_db_mutex)

#define _S_LINE(x) #x
#define __S_LINE(x) _S_LINE(x)
#define __S_LINE__ __S_LINE(__LINE__)

#define str_safe_cpy(dest, src, size) \
	do { \
		strncpy((dest), (src), (size)); \
		dest[size] = 0; \
	} while (0)

#define sysmgr_crit(fmt,...) \
		do { \
			debug_log_print(sysmgr_log, eLOG_LEVEL_CRITICAL, __FUNCTION__, \
				__FILE__, __LINE__, (fmt), ##__VA_ARGS__); \
		} while(0)

#define sysmgr_err(fmt,...) \
	do { \
		debug_log_print(sysmgr_log, eLOG_LEVEL_ERROR, __FUNCTION__, \
			__FILE__, __LINE__, (fmt), ##__VA_ARGS__); \
	} while(0)

#define sysmgr_info(fmt,...) \
	do { \
		debug_log_print(sysmgr_log, eLOG_LEVEL_INFOR, __FUNCTION__, \
			__FILE__, __LINE__, (fmt), ##__VA_ARGS__); \
	} while(0)

#define sysmgr_dbg(fmt,...) \
	do { \
		debug_log_print(sysmgr_log, eLOG_LEVEL_DEBUG, __FUNCTION__, \
			__FILE__, __LINE__, (fmt), ##__VA_ARGS__); \
	} while(0)

#define sysmgr_trace_enter() \
	do { \
		debug_log_print(sysmgr_log, eLOG_LEVEL_TRACE, __FUNCTION__, \
			__FILE__, __LINE__, "[ENTER]\n"); \
	} while(0)

#define sysmgr_trace_exit() \
	do { \
		debug_log_print(sysmgr_log, eLOG_LEVEL_TRACE, __FUNCTION__, \
			__FILE__, __LINE__, "[EXIT ]\n"); \
	} while(0)

#define sysmgr_trace_line() \
	do { \
		debug_log_print(sysmgr_log, eLOG_LEVEL_TRACE, __FUNCTION__, \
			__FILE__, __LINE__, "[CHECK]\n"); \
	} while(0)

#if 1
#define sysmgr_log_init() \
	debug_log_init(&sysmgr_log, SYSMGR_LOG_FILE, 0, SYSMGR_LOG_LEVEL)
#else
#define sysmgr_log_init() \
	debug_log_init(&sysmgr_log, NULL, 0, eLOG_LEVEL_TRACE)
#endif

#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:		the pointer to the member.
 * @type:		the type of the container struct this is embedded in.
 * @member: 	the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({                      \
			const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
			(type *)( (char *)__mptr - offsetof(type,member) );})

#define buf_get_line_init(line_start, line_end, buf_start) \
({																			\
	line_start = NULL;														\
	line_end = buf_start;													\
})

#define buf_get_line(line_start, line_end, buf_start, buf_end) \
({																			\
	e_bool got_line = eBOOL_FALSE;											\
	do {																	\
		char *buf_char;														\
		line_start = line_end;												\
		if (line_start != buf_start) {										\
			line_start = line_end + 1;										\
		}																	\
		line_end = NULL;													\
		for (buf_char = line_start; buf_char <= buf_end; buf_char++) {		\
			if (*buf_char == '\n') {										\
				/* Skip blank line. */											\
				if (line_start != buf_char) {								\
					line_end = buf_char;									\
					*line_end = 0;											\
					break;													\
				}															\
			}																\
		}																	\
		if (line_end == NULL) {												\
			line_end = buf_end;												\
		}																	\
		if (line_end > line_start) {										\
			got_line = eBOOL_TRUE;											\
		}																	\
	} while (0);															\
	got_line;																\
})

/* Global variable declarations. */

	extern t_log_p sysmgr_log;

#ifdef __cplusplus
}				/* extern "C" */
#endif				/* __cplusplus */
#endif				/* __GUM_COMMON_H__ */
